/**
 * 创建一个用户类，用于存储用户信息，包括用户名，密码哈希和盐值
 *
 * @author bill
 */

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

//用户的密码经过哈希和加盐处理后存储，用户名和密码不会明文存储
public class User {
    private String username;
    private String passwordHash;
    private String salt;

    public User(String username, String password) {
        this.username = username;
        this.salt = generateSalt();
        this.passwordHash = hashPassword(password, salt);
    }

    public String getUsername() {
        return username;
    }

    public String getPasswordHash() {
        return passwordHash;
    }

    public String getSalt() {
        return salt;
    }

    /*
    generateSalt是一个私有方法，用于生成一个随机的盐值。盐值是加密算法中的一个概念，被用于提高密码的安全性。在这里，盐值是一个由16个随机字节组成的字节数组。
    首先，创建一个SecureRandom对象random，它是用于生成安全的随机数的类。
    然后，创建一个字节数组saltBytes，大小为16个字节。
    接下来，调用random对象的nextBytes方法，将随机生成的字节填充到saltBytes数组中。
    最后，将saltBytes数组转换成十六进制字符串，通过调用bytesToHex方法，然后将字符串作为方法的返回值。
     */
    private String generateSalt() {
        SecureRandom random = new SecureRandom();
        byte[] saltBytes = new byte[16];
        random.nextBytes(saltBytes);
        return bytesToHex(saltBytes);
    }
    /*
    hashPashword方法是用于将用户输入的密码进行哈希处理的，目的是为了增加密码的安全性。具体的实现过程如下：
    1.将密码和盐值拼接起来，得到passwordWithSalt这个字符串。
    2.使用SHA-256算法获取MessageDigest对象md。
    3.将拼接后的字符串passwordWithSalt转换成字节数组，并使用md.digest方法对其进行哈希处理。
    4.将哈希处理后的字节数组转换成十六进制字符串，再返回给调用者。
    这个方法的核心是使用SHA-256算法对密码和盐值进行哈希处理，这样可以避免密码被直接暴力破解。
    同时，为了防止彩虹表攻击，使用盐值来增加密码的随机性。
    最后，将哈希处理后的结果以十六进制字符串的形式返回给调用者，这样可以方便地进行存储和比对。
     */

    protected String hashPassword(String password, String salt) {
        String passwordWithSalt = password + salt;
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] hashBytes = md.digest(passwordWithSalt.getBytes());
            return bytesToHex(hashBytes);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }


    /*
    bytesToHex方法的作用是将一个byte数组转换成16进制字符串表示。具体实现过程为：
    1.创建一个StringBuilder对象，用于拼接16进制字符串。
    2.遍历byte数组中的每一个元素。
    3.使用String类的format方法将byte转换成2位16进制字符串，并将其追加到StringBuilder对象中。
    4.返回最终的16进制字符串。
    例如，如果输入的byte数组为{0x12, 0x34, (byte) 0xAB, (byte) 0xCD}，那么该方法返回的字符串为"1234abcd"。
     */
    private String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            hexString.append(String.format("%02x", b));
        }
        return hexString.toString();
    }
}

